iT邦幫忙

2024 iThome 鐵人賽

0
Kubernetes

一起來看 Kubernetes 官方文件吧!系列 第 15

Day15 - 一起來看 Kubernetes 官方文件吧!- Disruptions (干擾)

  • 分享至 

  • xImage
  •  

前言

今日目標

  • 了解 Disruptions 的機制

Disruptions (干擾)

https://kubernetes.io/docs/concepts/workloads/pods/disruptions/#pod-disruption-conditions

若要建立一個高可用的 APP,則需要更加認識在 pods 可能會發生的各種干擾類型

自願干擾 v.s 非自願干擾 (Voluntary and involuntary disruptions)

pods 不會自己消失,除非有人特別銷毀,或者出現了不可避免的硬體或軟體錯誤,
非自願干擾有以下情況:

  • node 的硬體故障
  • cluster admin 錯誤的刪除虛擬機,或者公有雲上的機器故障導致消失
  • kernel 錯誤
  • 因為 Node 資源不足導致 pod 被驅逐

以上處了資源不足以外,都不是僅特定於 k8s 平台上的問題,比較會是 nodes 本身的問題

自願干擾則包括 APP 所有者與集群管理者發起的操作, APP 所有者的操作包括有以下:

  • deployment 或其他管理 pods 的 controller 被刪除
  • 更新了 deployment 的 template 導致 pods 重啟
  • 直接刪除 pod

集群管理者做的以下動作也是:

  • 為了升級或是修復 node 時做的 Drain node
  • 為了將 cluster 規模縮小做的 Drain node
  • 主動刪除 pods,以允許其他 pod 使用該節點 (可能是資源問題)

日常使用中最常遇到出現干擾問題的,應該就是當要升級 cluster 時,做的 drain node 動作就會觸發 pdb (底下會討論到)
如果設定了 pdb,但是因為 drain Node 導致該 pods 無法符合 pdb 的話,drain node 動作就會永遠卡死 (若沒有設定 timeout 的話),因此在安排升級 k8s cluster 版本時,可以特別注意一下
另外也不是所有的自願干擾都會觸發 pbd,比如主動的 delete pods 動作並不會因為 pdb 的關係被擋住。

Dealing with disruptions

要避免非自願干擾影響到 cluster,可以做以下調整:

  • 確保所有 pods 的 requests 足夠
  • 確保需要有 HA 的 APP replicas 數量 (又分成 stateless 與 stateful 兩種 APP 的差異)
  • 在節點分配上,可以考慮以 zone 區分節點,或是以跨機架 (避免單機架損壞導致 APP 掛掉) 的方式分布

在一個基本的 k8s cluster 中,不會有自願干擾 (只會有 user 觸發的干擾),若是使用雲端託管的 k8s cluster,通常會有文件可以參考有哪些自願干擾會發生,而最常見會觸發自願干擾的行為有:

  • nodes 軟更新
  • 若有做 nodes autoscaling 也可能導致
  • 在 pods 中定義了 PriorityClasses,導致底優先順序的 pods 的驅逐

Pod disruption budgets (pods 干擾預算)

當某個 APP 希望能夠保持一定數量的可用狀態時,可以配置 PodDisruptionBudget(PDB),來確保此 APP 的 pods 不會少於一定數量
比如當某 APP 的配置為 .spec.replicas: 5 的話,代表 deployment 會建立 5 個 pods。如果配置 pdb 允許最少必須要有 3 個副本的話,當 Eviction API 觸發時 (通常是 drain node 觸發的),最多就是同時 2 的 pods 自願干擾 (也就是刪除並排到新的 nodes 上)

不過當 Deployment 進行 rolling update 時不受到 pdb 的限制,APP 更新期間的可用故障管理是在對應的 workload 資源定義的

pdb 可以設定兩種 “不健康的 pod 驅逐策略” (k8s 1.31 stable),官方建議設定 AlwaysAllow,差異為:

  • IfHealthyBudget:僅驅逐健康的 pods ,會導致 drain node 有負面影響,可能會因 pdb 設定的 APP 行為錯誤而阻止 drain,
  • AlwaysAllow:會驅逐 Running 但還不健康的 pods,與是否滿足 PDB 中的判決條件無關

筆者目前不大確定這兩者的差異,或許明天再嘗試實作看看會更清楚~
另外筆者也是第一次注意到有 Eviction API 的存在,此 API 可以指定某 pods 觸發 Eviction API,或許比起直接 delete pods 觸發重建 pods 更為優雅一些。

PodDisruptionBudget 例子

官方文件這邊的例子蠻清楚的,礙於篇幅就不逐條解釋了,我認為的幾個重點:

  • 當觸發 drain node 時,會確保 APP 的 pdb 符合條件 (pods 必須要是 available 狀態才會被記入 pdb 的數量),否則 drain node 會卡死
  • pods 狀態分成 available, terminating, starting, pending 四種
  • 在考慮維護 nodes or 執行 k8s cluster upgrade 時,pdb 會是一個考量的重要條件

而影響干擾的速度有以下變因:

  • APP 需要多少的 replicas
  • 優雅的關閉 instance(指的應該是pods) 需要多少時間
  • 新的 instance start up 需要多少時間
  • controller 的類型 (e.g. 一般來說,sts 會比 deployment 需要更多時間)
  • cluster 整體的資源容量

Pod disruption conditions

算是比較新的功能,會 pods 上面描述被干擾的原因,會寫在 reason 的欄位,有以下幾種:

  • PreemptionByScheduler:因為有更高優先權的 pods 建立,因此 scheduler 觸發的搶占資源情況
  • DeletionByTaintManager:由 kube-controller-manager 觸發,主要當 nodes 被打上了 NoExecute 的 taints 導致某 pods 無法再執行
  • EvictionByEvictionAPI:pods 被標記為 eviction (透過 k8s API)
  • DeletionByPodGC:當 pods 已經不被某 nodes 綁定,會由 Pod garbage collection 觸發
  • TerminationByKubelet:由 kubelet 觸發,可能是因為 node pressure 驅除 (最常見於 disk 空間不足),或是 graceful node shutdown,又或是有系統重要的 pods 造成的搶占。

筆者在看這段時,發現一個有趣的現象 (與此主題無關)
就是英文版的文件是寫此功能為 1.31 (stable)
而簡體中文版的文件是寫此功能為 1.26 (beta)
看來又是可以發 PR 說我有在 kubernetes 貢獻的經驗了 (誤

How to perform Disruptive Actions on your Cluster

當我們要針對 k8s cluster 內的所有 node 進行升級 (k8s or 系統本身的升級),可以規劃以下內容:

  • 預計可接受的停機時間
  • 故障轉移到另一座 cluster 的時間
    • 這樣就可以 no downtime,但是成本比較高,且需要處理同步等等等的問題可能也導致不容易
  • 確保 APP 可以持續提供服務,也可以使用 PDB,且不受干擾影響 (disruption-tolerant)
    • APP 不停機
    • 最少的資源複製
    • 可以使用更多的自動化
    • APP 要不受干擾影響不容易,但是這樣的 APP 同時也支持 auto-scale 的功能

Eviction API

https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/

上面有提到除了 drain node 之外,我們也可以透過 Eviction API 來主動觸發驅逐,就來試試看吧~

可以透過程式語言內的 SDK 呼叫,另外也可以直接使用 curl 指令來帶入資料觸發

先建立一個 pods,在 default ns 中且叫做 eviction-pods


❯ kubectl run eviction-pods --image=nginx

要使用 curl 的話,要先寫好一個 policy 檔案:

# eviction.json
{
  "apiVersion": "policy/v1",
  "kind": "Eviction",
  "metadata": {
    "name": "eviction-pods",
    "namespace": "default"
  }
}

這邊我們直接使用 apiserver 的憑證來測試 (因為需要 root 權限才能讀 key, 因此使用 sudo),並帶入 policy:

sudo curl -k -H 'Content-type: application/json'  --cacert /etc/kubernetes/pki/ca.crt \
    --key /etc/kubernetes/pki/apiserver-kubelet-client.key \
    --cert /etc/kubernetes/pki/apiserver-kubelet-client.crt \
    https://192.168.75.10:6443/api/v1/namespaces/default/pods/eviction-pods/eviction -d @eviction.json

會回傳:

{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Success",
  "code": 201
}%

查看 events 不會特別看到有 evitced 的狀態,僅有被 killing 的 events 出現

❯ k events
...
74s                      Normal    Started     Pod/eviction-pods    Started container eviction-pods
74s                      Normal    Created     Pod/eviction-pods    Created container eviction-pods
71s                      Normal    Killing     Pod/eviction-pods    Stopping container eviction-pods
...

結論

APP 的高可用性可以說是 k8s 最主要的強項,而對於管理 cluster 的人來說,確保 node 的日常維運不會影響到 APP 使用,且進行更新時做好規劃都是很重要的議題 ~

參考

https://kubernetes.io/docs/concepts/workloads/pods/disruptions/#pod-disruption-conditions

https://kubernetes.io/zh-cn/docs/tasks/run-application/configure-pdb/#unhealthy-pod-eviction-policy

https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/#eviction-api

https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/


上一篇
Day14 - 一起來看 Kubernetes 官方文件吧!- Container Lifecycle Hooks
下一篇
Day16 - 一起來看 Kubernetes 官方文件吧!- PodDisruptionBudget
系列文
一起來看 Kubernetes 官方文件吧!19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言